% Autor:
% Data: 24-11-2011

:- include('network_cannon.pl').

:- use_module(library(socket)).

% Read from chars
:- use_module(library(charsio)).

:- use_module(library(random)).

% Use threads? yes,no

server(Thread_Version, Port):-
                       server_(Thread_Version, Port).

server(Thread_Version):-
                        random(2048, 60000, Port),server_(Thread_Version, Port).
                        

server_(Thread_Version, Port):-
        abolish(use_threads/1), assert(use_threads(Thread_Version)),
        abolish(welcome/1), assert(welcome('Welcome to Cannon server\n')),
        abolish(clients/1), assert(clients([])),
        write('Server initiating at: '), write(Port), nl,
        create_server(Port).

create_server(Port):-
                     tcp_socket(Socket),
                     tcp_bind(Socket,Port),
                     tcp_listen(Socket,5),
                     tcp_open_socket(Socket,AcceptFd,_),
                     use_threads(R),
                     server_loop(AcceptFd, R).

% Single threaded version
server_loop(AcceptFd, no) :-
                      write('Single-threaded version running.'), nl,
                      tcp_accept(AcceptFd,Socket2, Client),
                      tcp_open_socket(Socket2,In,Out),
                      client_begin(In, Out, Client),
                      close_connection(In, Out),
                      write('Accepting new connections..\n').
                      %server_loop(AcceptFd, no).

% Multi threaded version
server_loop(Input, yes):-
                   write('Multi-threaded version running.'), nl,
                   tcp_accept(Input, Socket, Client),
                   thread_create(process_client(Socket, Client), _,
                      [ detached(true)
                      ]),
                   server_loop(Input, yes).
                   
process_client(Socket, Client):-
                       setup_call_cleanup(tcp_open_socket(Socket, In, Out),
                       client_begin(In, Out, Client),
                       close_connection(In, Out)).
                       
close_connection(In, Out) :-
        close(In, [force(true)]),
        close(Out, [force(true)]).
        
        
client_begin(In, Out, Client):-
                        welcome(Welcome),
                        write(Out, Welcome),
                        flush_output(Out),
                        flush,
                        client_init(In, Out, Client),
                        client_game(In, Out).
        
client_init(In, Out, Client):-
                     repeat,
                     write('Waiting greeting from: '), write(Client), nl,
                     process_input(In, Message),
                     process_message(0, Message),
                     write('Your game will now begin'), nl, !.
                     
client_game(In, Out):-
                %write menu ascii
                %possibly clean
                %list of commands, + help
                %process commands
                %process end
                process_input(In, Message),
                (process_message(4, Message) -> write('Ending the connection.'), nl ;
                write(Message), process_message_(Message, Out), client_game(In, Out)).
                


process_input(InputStream, Message):-
                           read_line_to_codes(InputStream, Codes),
                           atom_codes(Line, Codes),
                           write('Read: '), write(Line), nl,
                           Message = Line.

game_loop(_).

% initialize
process_message(0, initialize).

% end
process_message(4, bye).

% execute(Mov, Board)
% Mov = A3 B4
process_message_(execute(Player, Movement, Board), _):-
                                     write('Exec!'),
                                     execute_(String, List).

process_message_(game_end(Board), Out):-
                                  (game_end(Board, Winner) -> response(Out, Winner);
                                  response(Out, invalid)).

                                     
process_message_(Message, Out):-
                       write('Unknown request: '), write(Message), nl,
                       write(Out, 'invalid').



execute_(String, List):-
             write('String: '), write(String), nl,
             write('List: '), write(List), nl.

response(Out, Message):-
              write(Out, Message), !.

% TODO THIS
response(Out, Message):-
              append(OutMessage, 'ok(', OutMessage),
              append(OutMessage, Message, OutMessage),
              append(OutMessage, ')', OutMessage),
              write(OutMessage), nl.
              %write(Out, OutMessage).
